package top.lishuoboy.redis.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.*;
import top.lishuoboy.dependency.base.json.HuJsonUtil;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author lishuoboy
 * @date 2022/3/2 12:28
 */
@Slf4j
@Configuration
public class JedisConfig {
    @Value("${my.jedis.host}")
    private String host;
    @Value("${my.jedis.port}")
    private Integer port;

    /** 上 jedisPool 最好停用 jedis */
    @Bean
    Jedis jedis() {
        Jedis jedis = new Jedis(host, port);
        log.debug("jedis.ping()=={}", jedis.ping());
        return jedis;
    }

    /** 上 jedisPool 最好停用 jedis */
    @Bean
    JedisPool jedisPool() {
        /**
         * JedisPoolConfig 默认配置参数
         * {
         *   "lifo" : true,
         *   "fairness" : false,
         *   "maxWaitMillis" : -1,
         *   "minEvictableIdleTimeMillis" : 60000,
         *   "evictorShutdownTimeoutMillis" : 10000,
         *   "softMinEvictableIdleTimeMillis" : -1,
         *   "numTestsPerEvictionRun" : -1,
         *   "evictionPolicy" : null,
         *   "evictionPolicyClassName" : "org.apache.commons.pool2.impl.DefaultEvictionPolicy",
         *   "testOnCreate" : false,
         *   "testOnBorrow" : false,
         *   "testOnReturn" : false,
         *   "testWhileIdle" : true,
         *   "timeBetweenEvictionRunsMillis" : 30000,
         *   "blockWhenExhausted" : true,
         *   "jmxEnabled" : true,
         *   "jmxNamePrefix" : "pool",
         *   "jmxNameBase" : null,
         *   "maxTotal" : 8,
         *   "maxIdle" : 8,
         *   "minIdle" : 0
         * }
         */
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        log.debug("jedisPoolConfig==\n{}", HuJsonUtil.toJsonStr(jedisPoolConfig));

        /** 修改默认配置 */
        jedisPoolConfig.setMaxIdle(9000);   // 最大空闲连接
        jedisPoolConfig.setMaxTotal(9000);  // 最大连接数，比redis最大连接数10000小点，防止超过最大连接数，因为还有其它客户端连接。超过报错  ERR max number of clients reached
        jedisPoolConfig.setMaxWaitMillis(20000);  // 从连接池获取连接的最大等待时间

        /**
         * JedisSocketFactory 默认配置参数
         * {
         *   "hostAndPort" : {
         *     "host" : "localhost",
         *     "port" : 6379
         *   },
         *   "connectionTimeout" : 2000,
         *   "ssl" : false,
         *   "sslSocketFactory" : null,
         *   "sslParameters" : null,
         *   "hostnameVerifier" : null,
         *   "hostAndPortMapper" : null,
         *   "host" : "localhost",
         *   "port" : 6379,
         *   "description" : "localhost:6379",
         *   "soTimeout" : 2000,
         *   "socketHostAndPort" : {
         *     "host" : "localhost",
         *     "port" : 6379
         *   }
         * }
         */
        JedisSocketFactory jedisSocketFactory = new DefaultJedisSocketFactory();
        log.debug("jedisSocketFactory==\n{}", HuJsonUtil.toJsonStr(jedisSocketFactory));

        /**
         * jedisClientConfig 默认配置参数
         * {
         *   "connectionTimeoutMillis" : 2000,
         *   "socketTimeoutMillis" : 2000,
         *   "blockingSocketTimeoutMillis" : 0,
         *   "user" : null,
         *   "password" : null,
         *   "database" : 0,
         *   "clientName" : null,
         *   "ssl" : false,
         *   "sslSocketFactory" : null,
         *   "sslParameters" : null,
         *   "hostnameVerifier" : null,
         *   "hostAndPortMapper" : null
         * }
         */

        JedisClientConfig jedisClientConfig = DefaultJedisClientConfig.builder()
            .database(0)
            .build();
        log.debug("jedisClientConfig==\n{}", HuJsonUtil.toJsonStr(jedisClientConfig));

        JedisPool jedisPool = new JedisPool(jedisPoolConfig, jedisSocketFactory, jedisClientConfig);
        return jedisPool;
    }

    /**
     * 配置哨兵连接池
     * 获取连接jedisSentinelPool.getResource()
     */
    @Bean
    JedisSentinelPool jedisSentinelPool() {
        JedisSentinelPool jedisSentinelPool = null;

        // 三个哨兵  哨兵的端口是 2+6379
        Set<String> sentinels = new HashSet<>(
            Arrays.asList(
                "192.168.1.101:26379",
                "192.168.1.102:26379",
                "192.168.1.103:26379"
            )
        );

//        new 哨兵连接池
//        jedisSentinelPool = new JedisSentinelPool(
//            "mymaster",
//            sentinels,
//            new JedisPoolConfig(),
//            2000, null, 0
//        );

        return jedisSentinelPool;
    }

    /**
     * 配置集群客户端 JedisCluster
     * 使用 jedisCluster.set("key", "value");
     */
    @Bean
    JedisCluster jedisCluster() {
        JedisCluster jedisCluster = null;

        // 三个哨兵  哨兵的端口是 2+6379
        Set<HostAndPort> jedisClusterNode = new HashSet<>(
            Arrays.asList(
                new HostAndPort("192.168.1.101", 6379),
                new HostAndPort("192.168.1.102", 6379),
                new HostAndPort("192.168.1.103", 6379)
            )
        );

        JedisClientConfig jedisClientConfig = DefaultJedisClientConfig.builder().build();
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();

        // 无集群环境，JedisCluster 连不上，严重影响启动速度，注释掉
//        jedisCluster = new JedisCluster(
//            jedisClusterNode,
//            jedisClientConfig,  // jedisClientConfig 所有参数见上面方法 jedisPool()
//            3,  // 最大尝试次数
//            jedisPoolConfig     // jedisPoolConfig   所有参数见上面方法 jedisPool()
//        );

        return jedisCluster;
    }
}